#ifndef __MSGHANDLE_H__
#define __MSGHANDLE_H__
#include "bytearrays.h"
#include "usertype.h"
#include "memorypool.h"
#include "msgclass.h"
#include <string.h>


/*
	struct wmsgdata 包含以下数据：
	int clientindex, from, to; 客户端索引，消息来源，消息目标
	int len, type; 消息中给socket的长度，消息类型
	void* param;消息的总数据，包括前面的5个int
	int current;book bend; param使用到的当前位置，标记当前消息是否已经读取完整或者使用完整

	这里，我们取消了所有带参数的构造函数，构造函数强制不带参数。
	我们定义了三个给这个结构赋值的函数。
	1.void makestream(int f, int t, int y, int c, int l, void* p);
	  这个函数的用途是，当main模块想给其它模块发消息时，需要并且只能使用这个函数来给这个结构赋值。
	  这里输入的长度和void*是匹配的，也就是说，长度是指void*的长度，并且不包括前面的5个int。
	  在这个函数的内部会保存输入参数长度＋12，并且生成一个输入长度＋20的数据，前20个byte保存固定数据，后面复制输入的void*。
	2.void msgstream(char* p);
	  这个函数的用途是，当msgrcv模块接收到一个void*的时候，我们需要生成一个wmsgdata，然后我们使用这个函数来初始化。
	3.void packetstream(int c, int f, int t, int packlen, char* p);
	  这个函数的用途是，当我们通过socket的receive收到一个包的时候，我们需要调用这个函数，来把这个包添加成为一个wmsgdata。
	  socket模块收到包以后，一定知道clientindex，from和to只能为2到0(wsocket到wmain)。
	  packlen是包的长度，p是包的数据。
	  这个函数应该是被pushstream调用，而不是socket模块直接调用，因为一次收到的包可能不完整。
*/

namespace WServer {

namespace MsgHandle {

extern pthread_mutex_t m_msgrcvMutex;
struct msginfo {
	int id;
	std::string name;
	std::string protocol;
	std::string luafunc;
	std::string comment;
	int msgto;
	int nolua;
};
extern std::map<int, msginfo> msglist;

struct wmsgdata {
	int clientindex, from, to;
	int len;//socket packet size; 包含了size+type+data 的数据包的总大小。
	int type;
	int current;
	bool bend;
	int memindex;
	char* param;//这是指向块内存,内容参见makestream()，是整个wmsgdata+data的数据。

	wmsgdata() {
		from = to = type = len = 0;
		clientindex = current = -1;
		bend = true;
		memindex = MemoryPool::instance()->applyMemoryPool();
		param = MemoryPool::instance()->m_memoryPool[memindex]->data;
		memset(param, 0, MEMORYPOOLSIZE);
	}
	wmsgdata(const wmsgdata& d) {
		from = d.from;to = d.to;type = d.type;len = d.len;
		clientindex = d.clientindex;current = d.current;
		bend = d.bend;
		memindex = d.memindex;
		param = d.param;
	}
	void makestream(int f, int t, int y, int c, int l, void* p) {
		clientindex = c+1;
		*(((int*)param)+0)= c+1;
		from = f;
		*(((int*)param)+1)= f;
		to = t;
		*(((int*)param)+2)= t;
		len = l+8;
		*(((int*)param)+3)= l+8;
		type = y;
		*(((int*)param)+4)= y;
		bend = true;
		current = 0;
		if (len > 0) memcpy(((char*)param)+20, p, l);
	}
	bool msgstream(char* p) {
		char* i = (char*)p;
		clientindex = (*(int*)i)-1;
		i += 4;
		from = *(int*)i;
		i += 4;
		to = *(int*)i;
		i += 4;
		len = *(int*)i;
		if (len >= MAX_SIZE) return false;
		i += 4;
		type = *(int*)i;
		i += 4;
		memcpy(param, p, len+12);
		bend = false;
		current = 12;
		return true;
	}
	void packetstream(int c, int f, int t, int packlen, char* p) {
		clientindex = c+1;
		from = f;
		to = t;
		char* i = (char*)p;
		len = *(int*)i;
		i += 4;
		type = *(int*)i;
		i += 4;

		if (msglist.find(type) == msglist.end()) return;
		if (len > MEMORYPOOLSIZE) return;

		if (len) {
			*(((int*)param)+0) = clientindex;
			*(((int*)param)+1) = from;
			*(((int*)param)+2) = to;
			memcpy((char*)param+12, p, packlen);
		}
		if (len == packlen) {
			bend = true;
			current = 0;
		}
		else {
			bend = false;
			current = packlen;
		}
	}
	int paramlen() {
		return len > 8 ? len - 8 : 0;
	}
	char* getparam() {
		return len > 8 ? (char*)param+20 : NULL;
	}
	~wmsgdata() {
		MemoryPool::instance()->releaseMemoryPool(memindex);
	}
};

void wserInitMsgHandle(int mindex);
void wserUninitMsgHandle();

void SendMessage2WMain(long type, int clientindex, int len, void* param);

void CreateMessage2WMain(int clientindex, MsgBaseClass& msgclass);
void CreateMessage2WMysql(int clientindex, MsgBaseClass& msgclass);
void CreateMessage2WSocket(int clientindex, MsgBaseClass& msgclass);
void CreateMessage2WPhp(int clientindex, MsgBaseClass& msgclass);
void CreateMessage2Simulator(int clientindex, MsgBaseClass& msgclass);

int getCurrentRound();
}

}

extern void HandleMessage(struct WServer::MsgHandle::wmsgdata* msg);

#endif //__MSGHANDLE_H__
